//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CRenderer10.cpp>
///	@path	~/src/graphics/dx10/
///	@date	2008/12/20
///	@desc	.

#include "config/config.h"

#include <set>
#include <map>

#include "lib/utilities/debug.h"
#include "lib/utilities/observer.h"
#include "lib/system/thread_debug.h"

#include "database/store/IFile.h"
#include "database/store/IFileSystem.h"

#include "graphics/DxHelpers.h"
#include "graphics/dx10/import_dx10.h"
#include "graphics/dx10/CRenderer10.h"
//#include "graphics/dx10/CBaseVertex9.h"
#include "graphics/dx10/CShadingPass10.h"
#include "graphics/dx10/CSimpleGeometry10.h"
#include "graphics/dx10/CFont10.h"
#include "graphics/dx10/CSprite10.h"
#include "graphics/dx10/CEffect10.h"
#include "graphics/dx10/CEffectPool10.h"
#include "graphics/dx10/CEffectCompiled10.h"
#include "graphics/dx10/CShaderAdapter10.h"
#include "graphics/dx10/CRenderState10.h"
#include "graphics/dx10/CTexture2D10.h"
// #include "graphics/dx10/COffscreenRenderTarget9.h"
#include "graphics/dx10/CColorRenderTarget10.h"
// #include "graphics/dx10/CDepthRenderTarget9.h"
#include "graphics/dx10/CRenderTargetSet10.h"
#include "graphics/dx10/CBlendState10.h"
#include "graphics/dx10/CVertexLayout10.h"
#include "graphics/dx10/CConstantVertex10.h"
#include "graphics/dx10/CDynamicVertex10.h"
#include "graphics/dx10/CConstantIndex10.h"
#include "graphics/dx10/CDynamicIndex10.h"

TRACE_CATEGORY( _S("Graphics/DX10/renderer") , TRACE_LV_TRACE );

namespace xeres {

	IMPL_IOBJECT_CLASS_DYNAMIC( CRenderer10 );

	// ctor
	CRenderer10::CRenderer10( void )
	{
	}

	// dtor
	CRenderer10::~CRenderer10( void )
	{
	}

	class CDefaultRenderTarget10 : public IRenderTarget
	{
	public:

		/// \ctor
		CDefaultRenderTarget10( ID3D10RenderTargetView * view )
			: m_view( view )
			, m_tex( NULL )
		{
			m_view->GetDesc( &m_desc );
			ID3D10Resource * res = NULL;
			m_view->GetResource( &res );
			res->QueryInterface( IID_ID3D10Texture2D , (void**)&m_tex );
			res->Release();
			m_tex->GetDesc( &m_texDesc );
		}

		/// \dtor
		virtual ~CDefaultRenderTarget10( void )
		{
			if( m_view )
			{
				m_view->Release();
				m_view = NULL;
			}
			if( m_tex )
			{
				m_tex->Release();
				m_tex = NULL;
			}
		}

		DECL_IOBJECT_CLASS( CDefaultRenderTarget10 , IRenderTarget );

		/// \impl
		virtual bool OnLostDevice( void )
		{
			if( m_view )
			{
				m_view->Release();
				m_view = NULL;
			}
			if( m_tex )
			{
				m_tex->Release();
				m_tex = NULL;
			}
			return true;
		}

		/// \impl
		virtual bool OnResetDevice( RefWeak<IDevice> device )
		{
			RefWeak<CDevice10> d3d10 = device;
			d3d10->GetDevice()->OMGetRenderTargets( 1 , &m_view , NULL );
			if( m_view == NULL )
			{
				TRACE_ERROR( _S("CDefaultRenderTarget10::OnResetDevice: Failed to get default render target.") );
				return false;
			}
			ID3D10Resource * res = NULL;
			m_view->GetResource( &res );
			res->QueryInterface( IID_ID3D10Texture2D , (void**)&m_tex );
			res->Release();

			m_view->GetDesc( &m_desc );
			m_tex->GetDesc( &m_texDesc );
			return true;
		}

		/// \brief	Apply render target to primary stage.
		virtual bool ApplyTarget( RefWeak<IDevice> device )
		{
			RefWeak<CDevice10> d3d10 = device;
			ID3D10RenderTargetView * pRTV = NULL;
			ID3D10DepthStencilView * pDSV = NULL;
			d3d10->GetDevice()->OMGetRenderTargets( 1 , &pRTV , &pDSV );
			d3d10->GetDevice()->OMSetRenderTargets( 1 , &m_view , pDSV );
			if( pRTV ) pRTV->Release();
			if( pDSV ) pDSV->Release();
			return true;
		}

		/// \impl
		virtual TextureType GetType( void )
		{
			return TEXTURE_2D;
		}

		/// \impl
		virtual DXFormat GetFormat( void )
		{
			return m_desc.Format;
		}

		/// \impl
		virtual Pair<int> GetSize( void )
		{
			return Pair<int>( m_texDesc.Width , m_texDesc.Height );
		}

		/// \impl
		virtual size_t GetDepth( void )
		{
			FATAL_ABORT( _S("Try to get depth from 2D texture.") );
			return 0;
		}

		/// \impl
		virtual bool IsWritable( void )
		{
			return false;
		}

		/// \impl
		virtual bool IsReadable( void )
		{
			return false;
		}

		/// \impl
		virtual bool Map( uint sub , ResourceMap& data )
		{
			return false;
		}

		/// \impl
		virtual bool ReadBack( uint sub , ResourceMap& data , bool readonly )
		{
			return false;
		}

		/// \impl
		virtual bool Unmap( uint sub )
		{
			return false;
		}

		/// \impl
		virtual bool Update( uint sub , const Box<uint>& size , const byte * data , uint row_pitch , uint depth_pitch )
		{
			return false;
		}

		/// \impl
		virtual IUnknown * GetTextureInterface( void )
		{
			return m_view;
		}

		/// \impl
		virtual IUnknown * GetRenderTargetInterface( void )
		{
			return m_view;
		}

	protected:

		ID3D10RenderTargetView *		m_view;
		ID3D10Texture2D *				m_tex;
		D3D10_RENDER_TARGET_VIEW_DESC 	m_desc;
		D3D10_TEXTURE2D_DESC			m_texDesc;
	};

	IMPL_IOBJECT_CLASS( CDefaultRenderTarget10 );

	class CDefaultDepthStencil10 : public IRenderTarget
	{
	public:

		/// \ctor
		CDefaultDepthStencil10( ID3D10DepthStencilView * view )
			: m_view( view )
			, m_tex( NULL )
		{
			m_view->GetDesc( &m_desc );
			ID3D10Resource * res = NULL;
			m_view->GetResource( &res );
			res->QueryInterface( IID_ID3D10Texture2D , (void**)&m_tex );
			res->Release();
			m_tex->GetDesc( &m_texDesc );
		}

		/// \dtor
		virtual ~CDefaultDepthStencil10( void )
		{
			if( m_view )
			{
				m_view->Release();
				m_view = NULL;
			}
			if( m_tex )
			{
				m_tex->Release();
				m_tex = NULL;
			}
		}

		DECL_IOBJECT_CLASS( CDefaultDepthStencil10 , IRenderTarget );

		/// \impl
		virtual bool OnLostDevice( void )
		{
			if( m_view )
			{
				m_view->Release();
				m_view = NULL;
			}
			if( m_tex )
			{
				m_tex->Release();
				m_tex = NULL;
			}
			return true;
		}

		/// \impl
		virtual bool OnResetDevice( RefWeak<IDevice> device )
		{
			RefWeak<CDevice10> d3d10 = device;
			d3d10->GetDevice()->OMGetRenderTargets( 1 , NULL , &m_view );
			if( m_view == NULL )
			{
				TRACE_ERROR( _S("CDefaultDepthStencil10::OnResetDevice: Failed to get default render target.") );
				return false;
			}
			ID3D10Resource * res = NULL;
			m_view->GetResource( &res );
			res->QueryInterface( IID_ID3D10Texture2D , (void**)&m_tex );
			res->Release();

			m_view->GetDesc( &m_desc );
			m_tex->GetDesc( &m_texDesc );
			return true;
		}

		/// \brief	Apply render target to primary stage.
		virtual bool ApplyTarget( RefWeak<IDevice> device )
		{
			RefWeak<CDevice10> d3d10 = device;
			ID3D10RenderTargetView * pRTV = NULL;
			d3d10->GetDevice()->OMGetRenderTargets( 1 , &pRTV , NULL );
			d3d10->GetDevice()->OMSetRenderTargets( 1 , &pRTV , m_view );
			if( pRTV ) pRTV->Release();
			return true;
		}

		/// \impl
		virtual TextureType GetType( void )
		{
			return TEXTURE_DEPTH;
		}

		/// \impl
		virtual DXFormat GetFormat( void )
		{
			return m_desc.Format;
		}

		/// \impl
		virtual Pair<int> GetSize( void )
		{
			return Pair<int>( m_texDesc.Width , m_texDesc.Height );
		}

		/// \impl
		virtual size_t GetDepth( void )
		{
			FATAL_ABORT( _S("Try to get depth from 2D texture.") );
			return 0;
		}

		/// \impl
		virtual bool IsWritable( void )
		{
			return false;
		}

		/// \impl
		virtual bool IsReadable( void )
		{
			return false;
		}

		/// \impl
		virtual bool Map( uint sub , ResourceMap& data )
		{
			return false;
		}

		/// \impl
		virtual bool ReadBack( uint sub , ResourceMap& data , bool readonly )
		{
			return false;
		}

		/// \impl
		virtual bool Unmap( uint sub )
		{
			return false;
		}

		/// \impl
		virtual bool Update( uint sub , const Box<uint>& size , const byte * data , uint row_pitch , uint depth_pitch )
		{
			return false;
		}

		/// \impl
		virtual IUnknown * GetTextureInterface( void )
		{
			return m_view;
		}

		/// \impl
		virtual IUnknown * GetRenderTargetInterface( void )
		{
			return m_view;
		}

	protected:

		ID3D10DepthStencilView *		m_view;
		ID3D10Texture2D *				m_tex;
		D3D10_DEPTH_STENCIL_VIEW_DESC 	m_desc;
		D3D10_TEXTURE2D_DESC			m_texDesc;
	};

	IMPL_IOBJECT_CLASS( CDefaultDepthStencil10 );

	// initialize
	void CRenderer10::Initialize( RefWeak<IDevice> device , RefWeak<IData> config )
	{
		// function only runs on main thread
		RUNNING_ON_THREAD( _S("main") );

		if( !device->IsA<CDevice10>() )
		{
			TRACE_ERROR( _S("CRenderer10::Initialize: Device API version mismatch.") );
			FATAL_ABORT( _S("Device API version mismatch.") );
		}

		m_device = device;

		m_device->AttachCallback( this );

		RefWeak<CDevice10> d3d10 = device;

		ID3D10RenderTargetView * pRTV = NULL;
		ID3D10DepthStencilView * pDSV = NULL;
		d3d10->GetDevice()->OMGetRenderTargets( 1 , &pRTV , &pDSV );
		m_defaultRenderTarget = new CDefaultRenderTarget10( pRTV );
		m_defaultDepthStencil = new CDefaultDepthStencil10( pDSV );

		// Add predefined macro
		SetEffectDefinition( "_D3D10" , "1" );
	}

	// finalize
	void CRenderer10::Finalize( void )
	{
		// function only runs on main thread
		RUNNING_ON_THREAD( _S("main") );

		OnLostDevice( m_device );

		m_includes.clear();
		m_defines.clear();
		m_cachedLayout.clear();
		m_defaultPool = NULL;
		m_defaultRenderTarget = NULL;
		m_defaultDepthStencil = NULL;
		m_device = NULL;
	}

	// GetColorOrder
	ColorOrder CRenderer10::GetColorOrder( void ) const
	{
		return COLOR_ORDER_RGBA;
	}

	// GetDevice
	RefWeak<IDevice> CRenderer10::GetDevice( void )
	{
		return m_device;
	}

	void CRenderer10::Tick( const Frame& frame )
	{
		COUNTER_GUARD( _S("overhead") );
	}

	bool CRenderer10::PreChangeMode( RefWeak<IDevice> device , void * oldSettings , void * newSettings )
	{
		return true;
	}

	bool CRenderer10::PostChangeMode( RefWeak<IDevice> device , void * settings )
	{
		return true;
	}

	bool CRenderer10::OnLostDevice( RefWeak<IDevice> device )
	{
		return true;
	}

	bool CRenderer10::OnResetDevice( RefWeak<IDevice> device )
	{
		return true;
	}

	// OnResizingSwapchain
	bool CRenderer10::OnResizingSwapchain( RefWeak<IDevice> device )
	{
		m_defaultRenderTarget = NULL;
		m_defaultDepthStencil = NULL;
		return true;
	}

	// OnResizedSwapchain
	bool CRenderer10::OnResizedSwapchain( RefWeak<IDevice> device )
	{
		ID3D10RenderTargetView * pRTV = NULL;
		ID3D10DepthStencilView * pDSV = NULL;
		m_device->GetDevice()->OMGetRenderTargets( 1 , &pRTV , &pDSV );
		m_defaultRenderTarget = new CDefaultRenderTarget10( pRTV );
		m_defaultDepthStencil = new CDefaultDepthStencil10( pDSV );
		return true;
	}
	
	bool CRenderer10::OnDestroyDevice( RefWeak<IDevice> device )
	{
		return true;
	}

	// AddDeviceResource
	void CRenderer10::AddDeviceResource( RefWeak<IDeviceResource> res )
	{
		// do nothing.
	}

	void CRenderer10::FreeDeviceResource( RefWeak<IDeviceResource> resource )
	{
		// do nothing.
	}

	// DefaultShadingPass
	RefPass<IPass> CRenderer10::DefaultShadingPass( void )
	{
		CShadingPass10 * pass = new CShadingPass10;
		return RefPass<IPass>( pass );
	}

	namespace
	{
		// Type converter mapping.

		class _TypeMap
		{
		public:

			typedef std::pair<DXGI_FORMAT,size_t> _TypeInfo;

			/// \instance
			static _TypeMap& instance( void )
			{
				static _TypeMap s_TypeMap_instance;
				return s_TypeMap_instance;
			}

			/// \brief	Get type info.
			const _TypeInfo& GetTypeInfo( VertexSlotType type )
			{
				XS_ASSERT( type >= 0 && type < VertexSlotType_last );
				return m_types[type];
			}

		private:

			/// \ctor
			_TypeMap( void )
			{
				m_types[VertexSlotType_Float1]		= _TypeInfo( DXGI_FORMAT_R32_FLOAT , sizeof(float)*1 );
				m_types[VertexSlotType_Float2]		= _TypeInfo( DXGI_FORMAT_R32G32_FLOAT , sizeof(float)*2 );
				m_types[VertexSlotType_Float3]		= _TypeInfo( DXGI_FORMAT_R32G32B32_FLOAT , sizeof(float)*3 );
				m_types[VertexSlotType_Float4]		= _TypeInfo( DXGI_FORMAT_R32G32B32A32_FLOAT , sizeof(float)*4 );
				m_types[VertexSlotType_Byte4]		= _TypeInfo( DXGI_FORMAT_R8G8B8A8_TYPELESS , sizeof(byte)*4 );
				m_types[VertexSlotType_Byte4Norm]	= _TypeInfo( DXGI_FORMAT_R8G8B8A8_UNORM , sizeof(byte)*4 );
				m_types[VertexSlotType_Short2] 		= _TypeInfo( DXGI_FORMAT_R16G16_TYPELESS , sizeof(short)*2 );
				m_types[VertexSlotType_Short2Norm] 	= _TypeInfo( DXGI_FORMAT_R16G16_SNORM , sizeof(short)*2 );
				m_types[VertexSlotType_Short4] 		= _TypeInfo( DXGI_FORMAT_R16G16B16A16_TYPELESS , sizeof(short)*4 );
				m_types[VertexSlotType_Short4Norm] 	= _TypeInfo( DXGI_FORMAT_R16G16B16A16_SNORM , sizeof(short)*4 );
				m_types[VertexSlotType_UShort2Norm] = _TypeInfo( DXGI_FORMAT_R16G16_UNORM , sizeof(short)*2 );
				m_types[VertexSlotType_UShort4Norm] = _TypeInfo( DXGI_FORMAT_R16G16B16A16_UNORM , sizeof(short)*4 );
				m_types[VertexSlotType_Half2] 		= _TypeInfo( DXGI_FORMAT_R16G16_FLOAT , sizeof(short)*2 );
				m_types[VertexSlotType_Half4] 		= _TypeInfo( DXGI_FORMAT_R16G16B16A16_FLOAT , sizeof(short)*4 );
				// color
				m_types[VertexSlotType_ColorRGBA] 	= _TypeInfo( DXGI_FORMAT_R8G8B8A8_UNORM , sizeof(byte)*4 );
				m_types[VertexSlotType_ColorfRGBA] 	= _TypeInfo( DXGI_FORMAT_R32G32B32A32_FLOAT , sizeof(float)*4 );
			}

			// @data
			std::map<VertexSlotType,_TypeInfo>	m_types;
		};

		// Vertex declaration converter.

		class _DeclConverter
		{
		public:

			/// \ctor
			_DeclConverter( const std::vector<VertexSlotDeclaration>& decl )
				: m_size( 0 )
				, m_slot( 0 )
				, m_decl( decl )
			{
				m_decl10.resize( decl.size() );
				for( size_t i = 0 , total = decl.size() ; i < total ; ++i )
				{
					D3D10_INPUT_ELEMENT_DESC * e10 = &m_decl10[i];
					memset( e10 , 0 , sizeof(D3D10_INPUT_ELEMENT_DESC) );
				}
			}

			// resolve
			bool resolve( void )
			{
				for( size_t i = 0 , total = m_decl.size() ; i < total ; ++i )
				{
					// see if new slot committed
					if( m_slot != m_decl[i].slot )
					{
						XS_ASSERT( m_slot < m_decl[i].slot );
						push_slot( i );
					}
					
					// convert
					if( !convert_entry( i ) )
						return false;
				}
				if( !m_currentLayout.empty() )
					push_slot( m_decl.size() - 1 );

				return true;
			}

			// push slot
			void push_slot( size_t index )
			{
				// new slot, end current
				Ref<CSlotLayout> slot = new CSlotLayout( m_size , m_currentLayout );
				m_slots.push_back( slot );
				m_size = 0;
				m_slot = m_decl[index].slot;
				m_currentLayout.clear();
			}

			size_t m_size , m_slot;
			const std::vector<VertexSlotDeclaration>& m_decl;
			std::vector<D3D10_INPUT_ELEMENT_DESC> m_decl10;
			std::vector< VertSlotDecl > m_currentLayout;
			std::vector< Ref<CSlotLayout> > m_slots;

		private:

			// convert entry
			bool convert_entry( size_t index )
			{
				const VertexSlotDeclaration& decl = m_decl[index];
				D3D10_INPUT_ELEMENT_DESC& desc = m_decl10[index];
				size_t input_size = 0 , output_size = 0;

				XS_ASSERT( decl.offset <= m_size );

				const _TypeMap::_TypeInfo& info = _TypeMap::instance().GetTypeInfo( decl.type );
				desc.SemanticName = decl.semantic;
				desc.SemanticIndex = 0;
				desc.Format = info.first;
				desc.InputSlot = m_slot;
				desc.AlignedByteOffset = D3D10_APPEND_ALIGNED_ELEMENT;
				desc.InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
				desc.InstanceDataStepRate = 0;

				VertSlotDecl slot_decl;
				slot_decl.offset = decl.offset;
				slot_decl.size = info.second;
				m_currentLayout.push_back( slot_decl );
				m_size += slot_decl.size;

				return true;
			}
		};

		/// \brief	Make shader with specific declaration.
		void MakeDefaultShader( AString& code , const std::vector<D3D10_INPUT_ELEMENT_DESC>& decl )
		{
			bool has_position = false;
			bool has_position_t = false;
			bool has_color = false;
			AString position_name;
			AString color_name;
			AString TransformPosition( "TransformPosition4" );
			char buf[64];

			code = "/* CRenderer10 Generated Default Shader */\n\n#include \"standard_fx.fxh\"\n\n";

			// Make input structure
			AString input_struct( "\nstruct VERTEX_IN{\n" );
			AString output_struct( "\nstruct VERTEX_OUT{\n" );
			for( size_t i = 0 , total = decl.size() ; i < total ; ++i )
			{
				const D3D10_INPUT_ELEMENT_DESC& desc = decl[i];
				const char * type = dxgi_to_hlsl_type( desc.Format );
				sprintf( buf , "param_%u" , i );

				input_struct += "\t";
				input_struct += type;
				input_struct += "\t";
				input_struct += buf;
				input_struct += " : ";
				input_struct += desc.SemanticName;
				input_struct += ";\n";

				AString semantic = desc.SemanticName;
				if( ( _stricmp( desc.SemanticName , "COLOR" ) == 0 ) && ( desc.SemanticIndex == 0 ) )
				{
					has_color = true;
					color_name = buf;
				}
				else if( ( _stricmp( desc.SemanticName , "POSITION" ) == 0 ) && ( desc.SemanticIndex == 0 ) )
				{
					has_position = true;
					position_name = buf;
					if( strcmp( type , "float3" ) == 0 )
					{
						TransformPosition = "TransformPosition3";
						type = "float4";
						semantic = "SV_POSITION";
					}
				}
				else if( _stricmp( desc.SemanticName , "POSITIONT" ) == 0 )
				{
					has_position_t = true;
					position_name = buf;
					type = "float4";
					semantic = "SV_POSITION";
				}
				else
				{
					// dont' write output.
					continue;
				}

				output_struct += "\t";
				output_struct += type;
				output_struct += "\t";
				output_struct += buf;
				output_struct += " : ";
				output_struct += semantic;
				output_struct += ";\n";
			}
			input_struct += "};\n\n";
			output_struct += "};\n\n";

			code += input_struct;
			code += output_struct;

			// vertex shader
			code += "VERTEX_OUT DefaultVS( VERTEX_IN input ) {\n\tVERTEX_OUT output;\n";
			if( has_color )
			{
				code += "\toutput." + color_name + "= input." + color_name + ";\n";
			}
			if( has_position_t )
			{
				// transformed position
				code += "\toutput." + position_name + "= float4(input." + position_name + ".xyz,1);\n";
			}
			else
			{
				// needs transform
				code += "\toutput." + position_name + "=" + TransformPosition + "(input." + position_name + ");\n";
			}
			code += "\treturn output;\n}\n";

			code += "float4 DefaultPS( VERTEX_OUT input ) : SV_Target {\n";
 
			if( has_color )
			{
				code += "\treturn input." + color_name + ";\n}\n";
			}
			else
			{
				code += "\treturn float4(1,1,1,1);\n}\n";
			}

			code += "technique10 DefaultMaterial{\n"
				"\tpass p0{\n"
				"\t\tSetBlendState( RegularBlending , float4(1,1,1,1) , 0xffffffff );\n"
				"\t\tSetVertexShader( CompileShader( vs_4_0 , DefaultVS() ) );\n"
				"\t\tSetGeometryShader( NULL );\n"
				"\t\tSetPixelShader( CompileShader( ps_4_0 , DefaultPS() ) );\n"
				"\t}\n}\n";
		}
	}

	// DeclareVertexLayout
	RefPass<IVertexLayout> CRenderer10::DeclareVertexLayout( const std::vector<VertexSlotDeclaration>& decl )
	{
		if( decl.empty() )
		{
			TRACE_ERROR( _S("CRenderer10::DeclareVertexLayout: Invalid declaration count.") );
			return NULL;
		}
		// sort declaration
		//std::sort( decl.begin() , decl.end() , VertexSlotDeclaration::SortDecl() );

		AString signature = VertexSlotDeclaration::make_signature( decl );
		dict< AString , Ref<IVertexLayout> >::iterator it = m_cachedLayout.find( signature );
		if( it != m_cachedLayout.end() )
			return it->second;

		// try to convert declaration to dx10 decl.
		
		_DeclConverter converter( decl );
		if( !converter.resolve() )
		{
			return NULL;
		}

		AString code;
		MakeDefaultShader( code , converter.m_decl10 );

		Ref<IEffect> effect = CreateEffect( code.c_str() , code.size() , m_defaultPool );
		Ref<CTechnique10> technique = effect->GetTechnique( "DefaultMaterial" );
		const void * shader_signature = technique->GetSignature();
		size_t signature_size = technique->GetSignatureSize();
		
		ID3D10InputLayout * pLayout = NULL;
		HRESULT hr = m_device->GetDevice()->CreateInputLayout( &(converter.m_decl10.front()) , converter.m_decl10.size() ,
			shader_signature , signature_size , &pLayout );
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::DeclareVertexLayout: Failed to create input layout of default shader: %s") ,
				d3d_get_err(hr) );
			return NULL;
		}
		Ref<CShaderAdapter10> adapter = new CShaderAdapter10( pLayout , technique );
		Ref<IVertexLayout> retval = new CVertexLayout10( adapter , converter.m_decl10 , converter.m_slots );
		m_cachedLayout[signature] = retval;
		return retval;
	}

	// create dynamic vertex
	RefPass<IVertexBuffer> CRenderer10::CreateDynamicVertex( RefWeak<ISlotLayout> layout , size_t vertex_count ,
		const void * init_data , size_t size )
	{
		size_t stride = layout->GetLayoutSize();
		size_t total_size = stride * vertex_count;
		if( init_data )
		{
			XS_ASSERT( total_size == size );
		}

		// FIXME ! Should create a resource provider instead of raw data
		D3D10_BUFFER_DESC vdesc = {
			total_size ,
			D3D10_USAGE_DYNAMIC ,
			D3D10_BIND_VERTEX_BUFFER ,
			D3D10_CPU_ACCESS_WRITE ,
			0
		};
		D3D10_SUBRESOURCE_DATA vdata = { init_data , 0 , 0 };

		ID3D10Buffer * pVertexBuffer = NULL;
		HRESULT hr = m_device->GetDevice()->CreateBuffer( &vdesc , ( init_data != NULL ) ? &vdata : NULL , &pVertexBuffer );
		if( FAILED( hr ) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateDynamicVertex: Failed to create vertex buffer: %s") ,
				d3d_get_err( hr ) );
			return NULL;
		}
		CDynamicVertex10 * vertex = new CDynamicVertex10( pVertexBuffer , vertex_count , stride );
		return RefPass<IVertexBuffer>( vertex );
	}

	// create immutable vertex
	RefPass<IVertexBuffer> CRenderer10::CreateConstantVertex( RefWeak<ISlotLayout> layout , size_t vertex_count ,
		const void * init_data , size_t size )
	{
		size_t stride = layout->GetLayoutSize();
		size_t total_size = stride * vertex_count;
		XS_ASSERT( total_size == size );
		XS_ASSERT( init_data );

		// FIXME ! Should create a resource provider instead of raw data
		D3D10_BUFFER_DESC vdesc = {
			total_size ,
			D3D10_USAGE_IMMUTABLE ,
			D3D10_BIND_VERTEX_BUFFER ,
			0,
			0
		};
		D3D10_SUBRESOURCE_DATA vdata = { init_data , 0 , 0 };

		ID3D10Buffer * pVertexBuffer = NULL;
		HRESULT hr = m_device->GetDevice()->CreateBuffer( &vdesc , &vdata , &pVertexBuffer );
		if( FAILED( hr ) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateConstantVertex: Failed to create vertex buffer: %s") ,
				d3d_get_err( hr ) );
			return NULL;
		}
		CConstantVertex10 * vertex = new CConstantVertex10( pVertexBuffer , vertex_count , stride );
		return RefPass<IVertexBuffer>( vertex );
	}

	// CreateDynamicIndex
	RefPass<IVertexIndex> CRenderer10::CreateDynamicIndex( size_t count , size_t size , const void * init_data )
	{
		DXGI_FORMAT format = DXGI_FORMAT_FORCE_UINT;
		if( size / count == sizeof(short) )
		{
			format = DXGI_FORMAT_R16_UINT;
		}
		else if( size / count == sizeof(int32) )
		{
			format = DXGI_FORMAT_R32_UINT;
		}
		else
		{
			TRACE_ERROR( _S("CRenderer10::CreateDynamicIndex: Size of index mismatch, per index size must be 16bit or 32bit." ) );
			return NULL;
		}

		// FIXME ! Should create a resource provider instead of raw data
		D3D10_BUFFER_DESC vdesc = {
			size ,
			D3D10_USAGE_IMMUTABLE ,
			D3D10_BIND_INDEX_BUFFER ,
			D3D10_CPU_ACCESS_WRITE ,
			0
		};
		D3D10_SUBRESOURCE_DATA vdata = { init_data , 0 , 0 };

		ID3D10Buffer * pIndexBuffer = NULL;
		HRESULT hr = m_device->GetDevice()->CreateBuffer( &vdesc , ( init_data != NULL ) ? &vdata : NULL , &pIndexBuffer );
		if( FAILED( hr ) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateDynamicIndex: Failed to create vertex buffer: %s") ,
				d3d_get_err( hr ) );
			return NULL;
		}
		CDynamicIndex10 * index = new CDynamicIndex10( pIndexBuffer , count , format );
		return RefPass<IVertexIndex>( index );
	}

	// CreateConstantIndex
	RefPass<IVertexIndex> CRenderer10::CreateConstantIndex( size_t count , size_t size , const void * init_data )
	{
		XS_ASSERT( init_data );
		DXGI_FORMAT format = DXGI_FORMAT_FORCE_UINT;
		if( size / count == sizeof(short) )
		{
			format = DXGI_FORMAT_R16_UINT;
		}
		else if( size / count == sizeof(int32) )
		{
			format = DXGI_FORMAT_R32_UINT;
		}
		else
		{
			TRACE_ERROR( _S("CRenderer10::CreateConstantIndex: Size of index mismatch, per index size must be 16bit or 32bit." ) );
			return NULL;
		}

		// FIXME ! Should create a resource provider instead of raw data
		D3D10_BUFFER_DESC vdesc = {
			size ,
			D3D10_USAGE_IMMUTABLE ,
			D3D10_BIND_INDEX_BUFFER ,
			0 ,
			0
		};
		D3D10_SUBRESOURCE_DATA vdata = { init_data , 0 , 0 };

		ID3D10Buffer * pIndexBuffer = NULL;
		HRESULT hr = m_device->GetDevice()->CreateBuffer( &vdesc , &vdata , &pIndexBuffer );
		if( FAILED( hr ) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateConstantIndex: Failed to create vertex buffer: %s") ,
				d3d_get_err( hr ) );
			return NULL;
		}
		CConstantIndex10 * index = new CConstantIndex10( pIndexBuffer , count , format );
		return RefPass<IVertexIndex>( index );
	}

	// create simple geometry
	RefPass<IGeometry> CRenderer10::CreateSimplePolygon(
		TopologyType type ,
		RefWeak<IVertexLayout> layout ,
		size_t vertex_count ,
		const void * vertex_data ,
		size_t index_count ,
		const ushort * index_data )
	{
		TRACK_FUNCTION_SCOPE();

		// check geometry type
		D3D10_PRIMITIVE_TOPOLOGY prim_type = d3d_topology_type10( type );
		size_t count = d3d_prim_count( type , vertex_count , index_count );

		if( prim_type == D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED )
		{
			TRACE_ERROR( _S("CRenderer10::CreateSimplePolygon: Triangle fan is not supported in DX10.") );
			return NULL;
		}

		// create buffer
		RefWeak<ISlotLayout> slot = layout->GetSlot( 0 );
		size_t stride = slot->GetLayoutSize();

		D3D10_BUFFER_DESC vdesc = {
			stride * vertex_count ,
			D3D10_USAGE_IMMUTABLE ,
			D3D10_BIND_VERTEX_BUFFER ,
			0,
			0
		};
		D3D10_SUBRESOURCE_DATA vdata = { vertex_data , 0 , 0 };
		ID3D10Buffer * pVertexBuffer = NULL;
		HRESULT hr = m_device->GetDevice()->CreateBuffer( &vdesc , &vdata , &pVertexBuffer );
		if( FAILED( hr ) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateSimplePolygon: Failed to create vertex buffer: %s") ,
				d3d_get_err( hr ) );
			return NULL;
		}

		ID3D10Buffer * pIndexBuffer = NULL;
		if( index_data )
		{
			D3D10_BUFFER_DESC idesc = {
				sizeof(ushort) * index_count ,
				D3D10_USAGE_IMMUTABLE ,
				D3D10_BIND_VERTEX_BUFFER ,
				0,
				0
			};
			D3D10_SUBRESOURCE_DATA idata = { index_data , 0 , 0 };
			hr = m_device->GetDevice()->CreateBuffer( &idesc , &idata , &pIndexBuffer );
			if( FAILED( hr ) )
			{
				TRACE_ERROR( _S("CRenderer9::CreateSimplePolygon: Failed to create index buffer: %s") ,
					d3d_get_err( hr ) );
				return NULL;
			}
		}

		CSimpleGeometry10 * retval =
			new CSimpleGeometry10( layout , stride , vertex_count , count , prim_type , pVertexBuffer , pIndexBuffer );
		return RefPass<IGeometry>( retval );
	}

	// create geometry from vertices
	RefPass<IGeometry> CRenderer10::CreateGeometry(
		TopologyType type ,
		std::vector< RefWeak<IVertexBuffer> >& vertices )
	{
		return NULL;
	}

	RefPass<IFont> CRenderer10::CreateFont( const WString& faceName ,
			int height , int width , int weight , bool italic , bool highQuality , bool scalable )
	{
		ID3D10Device * device = m_device->GetDevice();

		ID3DX10Font * font = NULL;
		HRESULT hr = dx10::D3DX10CreateFont(
			device ,
			height , width , weight ,
			scalable ? 0 : 1 ,
			italic ,
			DEFAULT_CHARSET ,
			OUT_DEFAULT_PRECIS ,
			highQuality ? CLEARTYPE_NATURAL_QUALITY : DEFAULT_QUALITY ,
			DEFAULT_PITCH | FF_DONTCARE ,
			faceName.c_str() , &font );

		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateFont: Failed to create font <%s>: %s") , faceName.c_str() ,
				d3d_get_err(hr) );
			return NULL;
		}

		CFont10 * font10 = new CFont10( font );
		return RefPass<IFont>( font10 );
	}

	RefPass<ISprite> CRenderer10::CreateSprite( void )
	{
		ID3D10Device * device = m_device->GetDevice();

		ID3DX10Sprite * sprite = NULL;
		HRESULT hr = dx10::D3DX10CreateSprite( device , 256 , &sprite );
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateSprite: Failed to create sprite: %s") , d3d_get_err(hr) );
			return NULL;
		}

		CSprite10 * sprite10 = new CSprite10( sprite );
		return RefPass<ISprite>( sprite10 );
	}

	// CreateTextureForSprite
	RefPass<ITexture> CRenderer10::CreateTextureForSprite( int width , int height )
	{
		// create rgba format texture, for sprite rendering
 		ID3D10Texture2D * pTexture = NULL;
		ID3D10ShaderResourceView * sview = NULL;

		CD3D10_TEXTURE2D_DESC desc( DXGI_FORMAT_R8G8B8A8_UNORM , width , height , 1 , 1 , D3D10_BIND_SHADER_RESOURCE ,
			D3D10_USAGE_DYNAMIC , D3D10_CPU_ACCESS_WRITE );
 		HRESULT hr = (*m_device)->CreateTexture2D( &desc , NULL , &pTexture );

		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateTextureForSprite: Failed to create texture: %s") , d3d_get_err(hr) );
			return NULL;
		}
		hr = m_device->GetDevice()->CreateShaderResourceView( pTexture , NULL , &sview );
		if( FAILED(hr) )
		{
			pTexture->Release();
			TRACE_ERROR( _S("CRenderer10::CreateTextureForSprite: Failed to create render target: %s") , d3d_get_err(hr) );
			return NULL;
		}

		CShaderTexture2D10 * tex = new CShaderTexture2D10( pTexture , sview );
		return RefPass<ITexture>(tex);
	}
	
	// CreateColorRenderTarget
	RefPass<IRenderTarget> CRenderer10::CreateColorRenderTarget( int width , int height )
	{
		ID3D10Texture2D * tex = NULL;
		ID3D10RenderTargetView * view = NULL;
		ID3D10ShaderResourceView * sview = NULL;

		CD3D10_TEXTURE2D_DESC desc( DXGI_FORMAT_R8G8B8A8_UNORM , width , height , 1 , 1 ,
			D3D10_BIND_RENDER_TARGET|D3D10_BIND_SHADER_RESOURCE ,
			D3D10_USAGE_DEFAULT , 0 );
		HRESULT hr = m_device->GetDevice()->CreateTexture2D( &desc , NULL , &tex );
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateColorRenderTarget: Failed to create render target texture: %s") , d3d_get_err(hr) );
			return NULL;
		}
		hr = m_device->GetDevice()->CreateRenderTargetView( tex , NULL , &view );
		if( FAILED(hr) )
		{
			tex->Release();
			TRACE_ERROR( _S("CRenderer10::CreateColorRenderTarget: Failed to create render target: %s") , d3d_get_err(hr) );
			return NULL;
		}
		hr = m_device->GetDevice()->CreateShaderResourceView( tex , NULL , &sview );
		if( FAILED(hr) )
		{
			view->Release();
			TRACE_ERROR( _S("CRenderer10::CreateColorRenderTarget: Failed to create render target: %s") , d3d_get_err(hr) );
			return NULL;
		}

		Ref<CColorRenderTarget10> target = new CColorRenderTarget10( tex , view , sview );
		return target;
	}

	// CreateRenderTargetSet
	RefPass<IRenderTargetSet> CRenderer10::CreateRenderTargetSet( int width , int height )
	{
		// create depth stencil view
		ID3D10DepthStencilView * pDSV = NULL;
		ID3D10Texture2D * pDepthStencil = NULL;
		D3D10_TEXTURE2D_DESC descDepth;
		descDepth.Width = width;
		descDepth.Height = height;
		descDepth.MipLevels = 1;
		descDepth.ArraySize = 1;
		descDepth.Format = DXGI_FORMAT_D32_FLOAT;
		descDepth.SampleDesc.Count = 1;
		descDepth.SampleDesc.Quality = 0;
		descDepth.Usage = D3D10_USAGE_DEFAULT;
		descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
		descDepth.CPUAccessFlags = 0;
		descDepth.MiscFlags = 0;
		HRESULT hr = m_device->GetDevice()->CreateTexture2D( &descDepth, NULL, &pDepthStencil );
		if( FAILED( hr ) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateRenderTargetSet: Failed to create depth stencil texture: %s") , d3d_get_err(hr) );
			return NULL;
		}
		
		// Create the depth stencil view
		D3D10_DEPTH_STENCIL_VIEW_DESC descDSV;
		descDSV.Format = descDepth.Format;
		descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
		descDSV.Texture2D.MipSlice = 0;
		hr = m_device->GetDevice()->CreateDepthStencilView( pDepthStencil, &descDSV, &pDSV );
		// release texture whatever
		pDepthStencil->Release();
		if( FAILED( hr ) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateRenderTargetSet: Failed to create depth stencil view: %s") , d3d_get_err(hr) );
			return NULL;
		}

		// just create
		Ref<CRenderTargetSet10> targets = new CRenderTargetSet10( width , height , pDSV );
		return targets;
	}

	void CRenderer10::SetEffectDefinition( const AString& name , const AString& def )
	{
		m_defines[ name ] = def;
	}

	void CRenderer10::AddInclude( RefWeak<IFileSystem> filesystem , const WString& path )
	{
		WString fullpath( path );
		normalize_slash( fullpath.begin() , fullpath.end() , '/' );
		for( size_t i = 0 , total = m_includes.size() ; i < total ; ++i )
		{
			if( m_includes[i].m_fs == filesystem && m_includes[i].m_path == fullpath )
			{
				TRACE_WARNING( _S("CRenderer10::AddInclude: Include path has been defined <%s>.") , path.c_str() );
				return;
			}
		}
		_IncludeDir dir;
		dir.m_fs = filesystem;
		dir.m_path = fullpath;
		m_includes.push_back( dir );
	}

	void CRenderer10::DelInclude( RefWeak<IFileSystem> filesystem , const WString& path )
	{
		WString fullpath( path );
		normalize_slash( fullpath.begin() , fullpath.end() , '/' );
		for( size_t i = 0 , total = m_includes.size() ; i < total ; ++i )
		{
			if( m_includes[i].m_fs == filesystem && m_includes[i].m_path == fullpath )
			{
				m_includes.erase( m_includes.begin() + i );
				return;
			}
		}
		TRACE_WARNING( _S("CRenderer10::DelInclude: Include path has been deleted <%s>.") , path.c_str() );
	}

	namespace
	{
		// implementation of include class
		class _CDXInclude10 : public ID3D10Include
		{
		public:

			//@ ctor
			_CDXInclude10( std::vector< CRenderer10::_IncludeDir >& pathes )
				: m_includes( pathes )
			{
			}

			//@ dtor
			~_CDXInclude10( void )
			{
				ClearCache();
			}

			// Clear cache
			void ClearCache( void )
			{
				if( m_data.size() > 0 )
				{
					TRACE_WARNING( _S("_CDXInclude10::ClearCache: Include file cache is not all freed.") );

					for( std::set<void*>::iterator it = m_data.begin() , end = m_data.end() ;
						it != end ; ++it )
					{
						free( (*it) );
					}
				}
			}

			// A user-implemented method for opening and reading the contents of a shader #include file.
			virtual HRESULT __stdcall Open(
				D3D10_INCLUDE_TYPE IncludeType , LPCSTR pFileName , LPCVOID pParentData,
				LPCVOID * ppData , UINT * pBytes )
			{
				*ppData = NULL;
				*pBytes = 0;

				WString wFileName;
				mbs_to_wcs( pFileName , wFileName );

				// resolve input file name
				Ref<IFile> file;
				for( size_t i = 0 , total = m_includes.size() ; i < total ; ++i )
				{
					CRenderer10::_IncludeDir& dir = m_includes[i];
					file = dir.m_fs->OpenFile( dir.m_path + WString( L"/" ) + wFileName );
					if( file.IsValid() )
						break;
				}
				
				if( file.IsNull() )
				{
					TRACE_ERROR( _S("CRenderer10: Failed to open include file for effect compile <%s>") , wFileName.c_str() );
					return E_FAIL;
				}

				// read file
				DataInfo info;
				file->GetInfo( info );
				DWORD size = (DWORD)info.m_size , readSize = 0;
				void * data = malloc( size );
				readSize = (DWORD)file->Read( data , size );
				assert( size == readSize );

				*ppData = data;
				*pBytes = size;
				
				m_data.insert( data );

				return S_OK;
			}

			// A user-implemented method for closing a shader #include file.
			virtual HRESULT __stdcall Close( LPCVOID pData )
			{
				std::set<void *>::iterator it = m_data.find( (void*)pData );
				assert( it != m_data.end() );
				m_data.erase( it );
				free( (void*)pData );
				return S_OK;
			}

		private:

		//@ data

			std::vector< CRenderer10::_IncludeDir >	m_includes;
			std::set<void *>						m_data;
		};
	}

	RefPass<IEffect> CRenderer10::CreateEffect( const void * buffer , size_t len , RefWeak<IEffectPool> pool )
	{
		TRACK_FUNCTION_SCOPE();

		ID3D10Device * device = m_device->GetDevice();

		ID3D10EffectPool * pPool = NULL;
		if( pool.IsValid() )
		{
			RefWeak<CEffectPool10> pool10 = pool;
			pPool = pool10->GetEffectPool();
		}

		// prepare compilation
		HRESULT hr = S_OK;

		ID3D10Effect * effect = NULL;
		ID3D10Blob * error = NULL;

		// create defines
		D3D10_SHADER_MACRO * macro = static_cast<D3D10_SHADER_MACRO*>( alloca( sizeof(D3D10_SHADER_MACRO) * ( m_defines.size() + 1 ) ) );
		int count = 0;
		for( dict<AString,AString>::iterator it = m_defines.begin() , end = m_defines.end() ;
			it != end ; ++it , ++count )
		{
			macro[count].Name = it->first.c_str();
			macro[count].Definition = it->second.c_str();
		}
		macro[count].Name = NULL;
		macro[count].Definition = NULL;

		// create includes
		_CDXInclude10 includes( m_includes );

		// make compile flags
		DWORD hlsl_flags = 
#ifdef _DEBUG
			D3D10_SHADER_DEBUG | D3D10_SHADER_SKIP_OPTIMIZATION
#else
			0
#endif
		;

		DWORD fx_flags =
#ifdef _DEBUG
			0
#else
			0
#endif
		;

		hr = dx10::D3DX10CreateEffectFromMemory(
			buffer , (UINT)len , "" , macro , &includes , "fx_4_0" , hlsl_flags , fx_flags ,
			device , pPool , NULL , &effect , &error , NULL );
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateEffect: Failed to create effect: %S") ,
				error->GetBufferPointer() );
			XS_VERIFY( error->Release() == 0 );
			return NULL;
		}
		else if( error )
		{
			TRACE_INFO( _S("Compile info: %S") , error->GetBufferPointer() );
			XS_VERIFY( error->Release() == 0 );
			error = NULL;
		}

		// create effect
		CEffect10 * retval = new CEffect10( effect , pool );
		return RefPass< IEffect >( retval );
	}

	// CreateEffectPool
	RefPass<IEffectPool> CRenderer10::CreateEffectPool( const char * buffer , size_t len )
	{
		TRACK_FUNCTION_SCOPE();

		ID3D10Device * device = m_device->GetDevice();

		// prepare compilation
		HRESULT hr = S_OK;

		ID3D10EffectPool * pool = NULL;
		ID3D10Blob * error = NULL;

		// create defines
		D3D10_SHADER_MACRO * macro = static_cast<D3D10_SHADER_MACRO*>( alloca( sizeof(D3D10_SHADER_MACRO) * ( m_defines.size() + 1 ) ) );
		int count = 0;
		for( dict<AString,AString>::iterator it = m_defines.begin() , end = m_defines.end() ;
			it != end ; ++it , ++count )
		{
			macro[count].Name = it->first.c_str();
			macro[count].Definition = it->second.c_str();
		}
		macro[count].Name = NULL;
		macro[count].Definition = NULL;

		// create includes
		_CDXInclude10 includes( m_includes );

		// make compile flags
		DWORD hlsl_flags = 
#ifdef _DEBUG
			D3D10_SHADER_DEBUG | D3D10_SHADER_SKIP_OPTIMIZATION
#else
			0
#endif
		;

		DWORD fx_flags =
#ifdef _DEBUG
			0
#else
			0
#endif
		;

		hr = dx10::D3DX10CreateEffectPoolFromMemory(
			buffer , (UINT)len , "" , macro , &includes , "fx_4_0" , hlsl_flags , fx_flags ,
			device , NULL , &pool , &error , NULL );
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateEffectPool: Failed to create effect pool: %S") ,
				error->GetBufferPointer() );
			XS_VERIFY( error->Release() == 0 );
			return NULL;
		}
		else if( error )
		{
			TRACE_INFO( _S("Compile info: %S") , error->GetBufferPointer() );
			XS_VERIFY( error->Release() == 0 );
			error = NULL;
		}

		// create effect
		CEffectPool10 * retval = new CEffectPool10( pool );
		return RefPass< IEffectPool >( retval );
	}

	RefPass<IEffectCompiled> CRenderer10::CompileEffect( const char * src , size_t len , RefWeak<IEffectPool> pool )
	{
		TRACK_FUNCTION_SCOPE();

		ID3D10Blob * compiled = NULL;
		ID3D10Blob * error = NULL;

		HRESULT hr = S_OK;

		// create defines
		D3D10_SHADER_MACRO * macro = static_cast<D3D10_SHADER_MACRO*>( alloca( sizeof(D3D10_SHADER_MACRO) * ( m_defines.size() + 1 ) ) );
		int count = 0;
		for( dict<AString,AString>::iterator it = m_defines.begin() , end = m_defines.end() ;
			it != end ; ++it , ++count )
		{
			macro[count].Name = it->first.c_str();
			macro[count].Definition = it->second.c_str();
		}
		macro[count].Name = NULL;
		macro[count].Definition = NULL;

		// create includes
		_CDXInclude10 includes( m_includes );

		// make compile flags
		DWORD hlsl_flags = 
#ifdef _DEBUG
			D3D10_SHADER_DEBUG | D3D10_SHADER_SKIP_OPTIMIZATION
#else
			0
#endif
		;

		DWORD fx_flags =
#ifdef _DEBUG
			0
#else
			0
#endif
		;

		hr = dx10::D3DX10CompileFromMemory( src , (UINT)len , "" ,
			macro , &includes , NULL , "fx_4_0" , hlsl_flags , fx_flags , NULL , &compiled , &error , NULL );

		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CompileEffect: Failed to compile effect: %s") ,
				error->GetBufferPointer() );
			XS_VERIFY( error->Release() == 0 );
			return NULL;
		}

		if( error )
		{
			XS_VERIFY( error->Release() == 0 );
			error = NULL;
		}

		// create effect
		RefPass<IEffect> effect = CreateEffect(
			compiled->GetBufferPointer() , compiled->GetBufferSize() , pool );

		if( effect.IsNull() )
			return NULL;

		CEffectCompiled10 * retval = new CEffectCompiled10( RefWeak<IEffect>(effect) , compiled );
		return RefPass<IEffectCompiled>( retval );
	}

	// LinkEffect
	RefPass<IShaderAdapter> CRenderer10::LinkEffect( RefWeak<ITechnique> technique , RefWeak<IVertexLayout> layout )
	{
		RefWeak<CVertexLayout10> layout10 = layout;
		RefWeak<CTechnique10> tech10 = technique;
		ID3D10InputLayout * pLayout = NULL;
		const std::vector<D3D10_INPUT_ELEMENT_DESC>& desc = layout10->GetInputDesc();
		
		HRESULT hr = m_device->GetDevice()->CreateInputLayout( &desc.front() , desc.size() ,
			tech10->GetSignature() , tech10->GetSignatureSize() , &pLayout );
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::LinkEffect: Failed to create input layout: %s") ,
				d3d_get_err(hr) );
			return NULL;
		}
		CShaderAdapter10 * adapter = new CShaderAdapter10( pLayout , technique );
		return RefPass<IShaderAdapter>( adapter );
	}

	// GetDefaultRenderTarget
	RefWeak<IRenderTarget> CRenderer10::GetDefaultRenderTarget( void )
	{
		return m_defaultRenderTarget;
	}

	// GetDefaultDepthStencil
	RefWeak<IRenderTarget> CRenderer10::GetDefaultDepthStencil( void )
	{
		return m_defaultDepthStencil;
	}

	// RestoreDefaultRenderTarget
	void CRenderer10::RestoreDefaultRenderTarget( void )
	{
		m_defaultRenderTarget->ApplyTarget( m_device );
	}

	// RestoreDefaultDepthStencil
	void CRenderer10::RestoreDefaultDepthStencil( void )
	{
		m_defaultDepthStencil->ApplyTarget( m_device );
	}
	// CreateStateForAll
	RefPass<IRenderState> CRenderer10::CreateStateForAll( void )
	{
		ID3D10StateBlock * block = NULL;
		D3D10_STATE_BLOCK_MASK mask;
		dx10::D3D10StateBlockMaskEnableAll( &mask );
		HRESULT hr = dx10::D3D10CreateStateBlock( m_device->GetDevice() , &mask , &block );
		if( FAILED(hr) )
		{
			TRACE_ERROR( _S("CRenderer10::CreateStateForAll: Failed to create render state: %s") , d3d_get_err(hr) );
			return NULL;
		}
		CRenderState10 * state = new CRenderState10( block , &mask );
		return RefPass<IRenderState>( state );
	}
	// CreateBlendState
	RefPass<IBlendState> CRenderer10::CreateBlendState( BlendSet& blend )
	{
		return RefPass<IBlendState>( new CBlendState10( blend , m_device ) );
	}
	// SetTexture
	bool CRenderer10::SetTexture( int shader_type , int sampler , RefWeak<ITexture> texture )
	{
		ID3D10ShaderResourceView * view = NULL;
		if( texture.IsValid() )
		{
			texture->GetTextureInterface()->QueryInterface( IID_ID3D10ShaderResourceView , (void**)&view );
			if( view == NULL )
			{
				TRACE_ERROR( _S("CRenderer10::SetTexture: Invalid texture type to set: %s") ,
					texture->GetClassName().c_str() );
				return false;
			}
		}
		if( shader_type & SHADER_VS )
		{
			m_device->GetDevice()->VSSetShaderResources( sampler , 1 , &view );
		}
		if( shader_type & SHADER_PS )
		{
			m_device->GetDevice()->PSSetShaderResources( sampler , 1 , &view );
		}
		if( shader_type & SHADER_GS )
		{
			m_device->GetDevice()->GSSetShaderResources( sampler , 1 , &view );
		}
		if( view )
			view->Release();
		return true;
	}
	// RestoreDefaultState
	void CRenderer10::RestoreDefaultState( void )
	{
		m_device->GetDevice()->ClearState();
		RestoreDefaultRenderTarget();
		RestoreDefaultDepthStencil();
	}
	// SetDefaultPool
	void CRenderer10::SetDefaultPool( const AString& shader )
	{
		RefPass<IEffectPool> pool = CreateEffectPool( shader.c_str() , shader.size() );
		if( pool.IsValid() )
		{
			m_defaultPool = pool;
		}
	}
	// GetDefaultEffectPool
	RefWeak<IEffectPool> CRenderer10::GetDefaultEffectPool( void )
	{
		return m_defaultPool;
	}
	
} // namespace xeres
